

#include <string>
#include <iostream>
using namespace std;

// 产品 begin
class Car
{
public:
    virtual void speed() = 0;
};

class Lanboji : public Car
{
public:
    virtual void speed() override
    {
        cout << "i am lanboji,speed 400km/h" << endl;
    }
};

class LanbojiOne : public Car
{
public:
    virtual void speed() override
    {
        cout << "lanboji No 1, speed 300km/h" << endl;
    }
};

class LanbojiTwo : public Car
{
public:
    virtual void speed() override
    {
        cout << "lanboji No 2, speed 340km/h" << endl;
    }
};

class Ferrari : public Car
{
public:
    virtual void speed() override
    {
        cout << "i am ferrari,speed 380km/h" << endl;
    }
};

class FerrariOne : public Car
{
public:
    virtual void speed() override
    {
        cout << "Ferrari No 1, speed 333km/h" << endl;
    }
};

class FerrariTwo : public Car
{
public:
    virtual void speed() override
    {
        cout << "Ferrari No 2, speed 388km/h" << endl;
    }
};
// 产品 end

// 简单工厂模式 begin
class CarFactory
{
public:
    Car *getCar(std::string car)
    {
        if (!strncmp(car.c_str(), "lanboji", strlen("lanboji")))
        {
            return new Lanboji();
        }
        else if (!strncmp(car.c_str(), "ferrari", strlen("ferrari")))
        {
            return new Ferrari();
        }
        else
        {
            return NULL;
        }
    }
};
// 简单工厂模式 end

// 工厂方法模式 begin
class AbstractFactory
{
public:
    virtual Car *getCar() = 0;
};

class LanbojiFactory : public AbstractFactory
{
public:
    virtual Car *getCar() override
    {
        return new Lanboji();
    }
};

class FerrariFactory : public AbstractFactory
{
public:
    virtual Car *getCar() override
    {
        return new Ferrari();
    }
};
// 工厂方法模式 end

// 抽象工厂模式 begin
class AbstractAllFactory
{
public:
    virtual Car *getCar(std::string carName) = 0;
};

class LanbojiAllFactory : public AbstractAllFactory
{
public:
    virtual Car *getCar(std::string carName) override
    {
        if (!strncmp(carName.c_str(), "Lanboji1", strlen("Lanboji1")))
        {
            return new LanbojiOne();
        }
        else if (!strncmp(carName.c_str(), "Lanboji2", strlen("Lanboji2")))
        {
            return new LanbojiTwo();
        }
        else
        {
            return NULL;
        }
    }
};

class FerrariAllFactory : public AbstractAllFactory
{
public:
    virtual Car *getCar(std::string carName) override
    {
        if (!strncmp(carName.c_str(), "Ferrari1", strlen("Ferrari1")))
        {
            return new FerrariOne();
        }
        else if (!strncmp(carName.c_str(), "Ferrari2", strlen("Ferrari2")))
        {
            return new FerrariTwo();
        }
        else
        {
            return NULL;
        }
    }
};

class SuperFactory
{
public:
    AbstractAllFactory *getCarFactory(std::string carFactory)
    {
        if (!strncmp(carFactory.c_str(), "LanbojiFactory", strlen("LanbojiFactory")))
        {
            return new LanbojiAllFactory();
        }
        else if (!strncmp(carFactory.c_str(), "FerrariFactory", strlen("FerrariFactory")))
        {
            return new FerrariAllFactory();
        }
        else
        {
            return NULL;
        }
    }
};
// 抽象工厂模式 end

int main(int argc, char *argv[])
{
    std::string carFactoryName;
    std::string carName;
    if (argc == 1)
    {
        cout << "please input param" << endl;
        return 0;
    }

    if (argc == 2)
    {
        carName = argv[1];
    }

    if (argc == 3)
    {
        carFactoryName = argv[1];
        carName = argv[2];
    }

    // 简单工厂模式
    cout << "简单工厂模式:" << endl;
    CarFactory *carFactory = new CarFactory();
    Car *car = carFactory->getCar(carName);
    if (!car)
    {
        cout << "unkonw car name" << endl;
    }
    else
    {
        car->speed();
    }

    // 工厂方法测试
    cout << "工厂方法模式:" << endl;
    AbstractFactory *abstractFactory = NULL;
    if (!strncmp(carName.c_str(), "lanboji", strlen("lanboji")))
    {
        abstractFactory = new LanbojiFactory();
        abstractFactory->getCar()->speed();
    }
    else if (!strncmp(carName.c_str(), "ferrari", strlen("ferrari")))
    {
        abstractFactory = new FerrariFactory();
        abstractFactory->getCar()->speed();
    } else {
        cout << "unkonw car name" << endl;
    }

    //抽象工厂模式
    cout << "抽象工厂模式:" << endl;
    SuperFactory *superFactory = new SuperFactory();
    AbstractAllFactory *abstractAllFactory = superFactory->getCarFactory(carFactoryName);
    if (!abstractAllFactory)
    {
        cout << "unkonw car factory name" << endl;
    }
    else
    {
        car = abstractAllFactory->getCar(carName);
        if (!car)
        {
            cout << "unknow car name" << endl;
        }
        else
        {
            car->speed();
        }
    }

    return 0;
}